package org.codingq92.basic.queue;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 阻塞队列使用
 *
 * @author CodingQ92
 */
public class TestBlockingQueue {
    //创建时就得指定容量、也可以指定底层ReentrantLock锁是公平锁还是非公平锁
    private static final ArrayBlockingQueue<String> ARRAY_BLOCKING_QUEUE = new ArrayBlockingQueue<>(2);
    //创建时就得指定容量或者不指容量都可以、底层是读写锁
    private static final LinkedBlockingQueue<String> LINKED_BLOCKING_QUEUE = new LinkedBlockingQueue<>(2);

    public static void main(String[] args) throws InterruptedException {
//        useArrayBlockQueue();
//        useLinkedBlockQueue();
    }

    private static void useLinkedBlockQueue() throws InterruptedException {
        //添加元素到队尾 TODO add方法底层其实调用的还是offer方法
        LINKED_BLOCKING_QUEUE.add("1");
        LINKED_BLOCKING_QUEUE.add("2");
        System.out.println("add方法添加元素:" + LINKED_BLOCKING_QUEUE);
        LINKED_BLOCKING_QUEUE.offer("3");
        LINKED_BLOCKING_QUEUE.offer("4");
        System.out.println("offer方法添加元素:" + LINKED_BLOCKING_QUEUE);
        boolean offer = LINKED_BLOCKING_QUEUE.offer("5", 3, TimeUnit.SECONDS);
        System.out.println("offer方法带时间添加元素:" + LINKED_BLOCKING_QUEUE + ", 3秒内添加数据是否成功:" + offer);
        LINKED_BLOCKING_QUEUE.put("5"); //TODO 容量不够的时候会阻塞线程
        System.out.println("会阻塞的put方法添加元素:" + LINKED_BLOCKING_QUEUE);

        System.out.println("===========================================================");
        //移除并返回头部元素
        System.out.println("remove方法移除并返回头部元素:" + LINKED_BLOCKING_QUEUE.remove());
        System.out.println("remove方法移除后队列:" + LINKED_BLOCKING_QUEUE);
        System.out.println("poll方法移除并返回头部元素:" + LINKED_BLOCKING_QUEUE.poll());
        System.out.println("poll方法移除后队列:" + LINKED_BLOCKING_QUEUE);
        String poll = LINKED_BLOCKING_QUEUE.poll(3, TimeUnit.SECONDS);
        System.out.println("poll方法带时间获取元素:" + LINKED_BLOCKING_QUEUE + ", 3秒内获取数据成功?" + poll);
        String take = LINKED_BLOCKING_QUEUE.take(); //TODO 获取不到的时候会阻塞线程
        System.out.println("会阻塞的take方法获取元素:" + LINKED_BLOCKING_QUEUE + ", 获取数据成功?" + take);

        System.out.println("===========================================================");
        //获取队列头部的元素，但不移除
        System.out.println("peek方法获取队列头部的元素:" + LINKED_BLOCKING_QUEUE.peek());
        System.out.println("peek方法获取队列:" + LINKED_BLOCKING_QUEUE);
        System.out.println("element方法获取队列头部的元素:" + LINKED_BLOCKING_QUEUE.element());
        System.out.println("element方法获取队列:" + LINKED_BLOCKING_QUEUE);

        System.out.println("===========================================================");
        //清空队列
        LINKED_BLOCKING_QUEUE.clear();
        System.out.println("清空队列:" + LINKED_BLOCKING_QUEUE);

    }

    private static void useArrayBlockQueue() throws InterruptedException {
        //添加元素到队尾 TODO add方法底层其实调用的还是offer方法
        ARRAY_BLOCKING_QUEUE.add("1");
        ARRAY_BLOCKING_QUEUE.add("2");
        System.out.println("add方法添加元素:" + ARRAY_BLOCKING_QUEUE);
        ARRAY_BLOCKING_QUEUE.offer("3");
        ARRAY_BLOCKING_QUEUE.offer("4");
        System.out.println("offer方法添加元素:" + ARRAY_BLOCKING_QUEUE);
        boolean offer = ARRAY_BLOCKING_QUEUE.offer("5", 3, TimeUnit.SECONDS);
        System.out.println("offer方法带时间添加元素:" + ARRAY_BLOCKING_QUEUE + ", 3秒内添加数据是否成功:" + offer);
        ARRAY_BLOCKING_QUEUE.put("5"); //TODO 容量不够的时候会阻塞线程
        System.out.println("会阻塞的put方法添加元素:" + ARRAY_BLOCKING_QUEUE);

        System.out.println("===========================================================");
        //移除并返回头部元素
        System.out.println("remove方法移除并返回头部元素:" + ARRAY_BLOCKING_QUEUE.remove());
        System.out.println("remove方法移除后队列:" + ARRAY_BLOCKING_QUEUE);
        System.out.println("poll方法移除并返回头部元素:" + ARRAY_BLOCKING_QUEUE.poll());
        System.out.println("poll方法移除后队列:" + ARRAY_BLOCKING_QUEUE);
        String poll = ARRAY_BLOCKING_QUEUE.poll(3, TimeUnit.SECONDS);
        System.out.println("poll方法带时间获取元素:" + ARRAY_BLOCKING_QUEUE + ", 3秒内获取数据成功?" + poll);
        String take = ARRAY_BLOCKING_QUEUE.take(); //TODO 获取不到的时候会阻塞线程
        System.out.println("会阻塞的take方法获取元素:" + ARRAY_BLOCKING_QUEUE + ", 获取数据成功?" + take);

        System.out.println("===========================================================");
        //获取队列头部的元素，但不移除
        System.out.println("peek方法获取队列头部的元素:" + ARRAY_BLOCKING_QUEUE.peek());
        System.out.println("peek方法获取队列:" + ARRAY_BLOCKING_QUEUE);
        System.out.println("element方法获取队列头部的元素:" + ARRAY_BLOCKING_QUEUE.element());
        System.out.println("element方法获取队列:" + ARRAY_BLOCKING_QUEUE);

        System.out.println("===========================================================");
        //清空队列
        ARRAY_BLOCKING_QUEUE.clear();
        System.out.println("清空队列:" + ARRAY_BLOCKING_QUEUE);
    }
}
